/**	@file Ex.h 
 *	@brief Representation of mathematical expressions, fundamental type definitions and some exceptions. */
#ifndef Ex_majdo_
#define Ex_majdo_
#include <iostream>
#include <string>
#include <cassert>	
#include <exception>
#include <vector>
#include <sstream>
#include <list>
///	@brief Each elemnt from sympy-cpp library belongs to this namespace. 
namespace sympycpp {
class Sym;
class Number;
class Pow;
class Mul;
class Add;
class Fx;
/**	@brief Flag that marks a special memory management of functions.
 * 	The special memory management flag is an extra (last) parameter of marked functions. 
 * 	The main purpose to marking of the functions (that use memory unusually) is to forbid unaware usage of them. */
typedef enum {
	/**This flag means "stealing of all input memory". The marked functions exploit
	 * the allocated memory from their input parameters. All pointers from the parameters 
	 * should be set to nul by the stealing functions. */ 
		STEALING
} allocationPolicy;
///	@brief Information about a relationship between two expressions.
typedef enum {
	/// The relationship is not detected.
		INCOMPATIBLE,
	/// The both compared expressions are numbers.	
		NUMBER_NUMBER,
	/// The expressions are compatible and neither is multiple. 	
		PLAIN_PLAIN,
	/// The expressions are multiple.	
		MULTIPLE_MULTIPLE,
	/// The second expression is a multiple of the first.	
		PLAIN_MULTIPLE,
	/// The first expression is a multiple of the second.	
		MULTIPLE_PLAIN,
	/// The both expressions are powers and their bases are compatible.	
		BASE_BASE,
	/// The first expression is a power and its base is compatible with the second expression.	
		BASE_PLAIN,
	/// The first expression is compatible with the base of the second expression that is a power.	
		PLAIN_BASE
} compatibility;
///	@brief Information about type of class (expression). 
typedef enum { 
	/// a general expression == class Ex
		EX, 
	/// a number == class Number
		NUM,
	/// a symbol (a variable) == class Sym	 
		SYM, 
	/// a power == class Pow
		POW,
	/// an addition	== class Add
		ADD,
	/// a multiplication == class Mul
		MUL, 
	/// a function == class Fx
		FX 
} type_info;
///	@brief Representation of the expression sign.
///	It increases lucidity of source codes. 
typedef bool Sign;
///	@brief positive sign
#define plus true 
///	@brief negative sign 
#define minus false
///	@brief  Exception: The division by zero. 
class ZeroDivision: public std::exception {
	virtual const char * what() const throw() {
		return "The division by zero.";
	}
};
///	@brief Exception: An expression is not compatible with int.
class NotInt: public std::exception {
	virtual const char * what() const throw() {
		return "The number is not compatible with type int.";
	}
};
/**	@class Ex 
 *	@brief Representation of general mathematical expressions.	
 *	The class Ex is a common parent in the inheritance tree.
 *	Every class that represents a type of expressions (numbers, 
 *	variables, additions, multiplications, powers and functions) is derived from Ex. 
 *	This common parent provides simple manipulation with the various types of expressions by pointers.
 *	This class covers only one property (the expression sign). It also provides the expression type detection 
 *	and some interfaces designed for descendents. 
 *	Construction of the Ex is available only for its descendants (in other cases, it's a nonsense). */
class Ex {
	///	@brief The information about the type of the stored expression.
	type_info typeInfo_;	
protected:
	/// 	@brief The sign of the represented expression.
	Sign sign_;		
	///	@brief Construction of a positive expression by its type.
	Ex(const type_info & t) : typeInfo_(t), sign_(plus) {}
public:
	///	@brief Empty destructor.
	virtual ~Ex() {}
	/**	@brief The transformation of the stored expression to a suitable infix tree.
	 * 	The created infix tree is a multinomial tree (same as the inner representation).
	 * 	The tree is printed from left to riht. The root of the tree is placed on the left side,
	 * 	the root's "operands" (if they exist) are situated in the next column on the right, 
	 * 	the operands of any expression are located in the next right column.
	 * 	@param is the indentation of the printed node from the left side. */
	virtual std::string treeView(const int i) const { return "";}
	/** 	@brief Identification of the type of the stored expression.
	 * 	This runtime detection is alternative to virtual functions. 
	 *	Sometimes, it's useful make a nasty manipulation inside of expressions and 
	 *	there is a place for this identification.
	 * 	@see type_info */
	type_info type() const {
		return typeInfo_;
	}
	/**	@brief The sign of the stored expression.
	 * 	@see Sign
	 *	@see plus or minus 	
	 *	@retval plus
	 *	@retval minus */	
	Sign sign() const {
		return sign_;
	}
	/**	@brief Change of the sign.
	 *	@param s is a new sign [plus or minus] 
	 *	@see Sign
	 *	@see plus or minus */	
	virtual void sign(const Sign s) {
		sign_ = s;
	}
	/**	@brief This is a real size (rsize) that indicates the number of the elementary subexpressions 
	 * 	( == the count of the variables and numbers) in the expression.
 	 * 	It's the number of all leafs in the tree thet represents the expression.
	 * 	@param all is special information that is used only by multiplications that are multiples (other expressions ignore it).
	 * 		 <br/>  <i>true --></i> means ignore the multiplicity of the actual expression (this omitting of multiplicity is not active in subexpressions)
	 * 		 <br/>  <i>false --></i> means to count in multiplicity as elementary subexpression */
	virtual size_t rsize(const bool all = true) const {
		return 1;
	}
	/**	@brief The actual size (asize) is the count of all immediate subexpressions.
	 * 	@return  count of operands in operations, one plus the actual size of the parameter of math functions, 
	 * 	and one for variables and numbers. */
	virtual size_t asize() const {
		return 1;
	}
	/**	@brief The count of subexpressions.
	 * 	@todo size() and asize() have same duties. (merge them) */
	virtual size_t size() const {
		return 1;
	}
	/**	@brief str() transforms expressions into the std::string.
	 *  	@todo Implement a pretty printing function.
	 *	@see unsigned_str() 	
	 *	@return infix form of Expression */	
	virtual std::string str() const {
		return "";
	}
	/**	@brief Transformation of the expression into the std::string (sign of the expression is ignored).
	 *	@see str() */	
	virtual std::string unsigned_str() const {
		return "";
	}
	/**	@brief Differentiation of a expression.	
	 * 	It makes differentiation of the expression with respect to the input variable.
	 *	@warning The function alocates new memory for returned expression. 
	 *	The class that invoke the differentiation is responsible for deleting of the returned expression.
	 *	@return  differentiation of the expression. */	
	virtual Ex * diff(const Sym & t) const {
		return 0;
	}
	/**	@brief The creation of a new identical expression (a clon).
	 * 	The clone is same like the source expression but objects don't share any memory.
	 *	@warning The function alocates new memory for returned expression. 
	 *	The class that invoke the differentiation is responsible for deleting of the returned expression. */
	virtual Ex * copy() const {
		 return new Ex(typeInfo_);
	}
	///	@brief Multiplicity of expression.
	virtual Number Multiplicity() const; 
	///	@brief Is the expression multiple?
	virtual bool isMultiple() const {
		return false;
	}
	///	@brief Is the expression a integer?
	virtual bool isInteger() const {
		return false;
	}
	///	@brief Is the expression a rational number?
	virtual bool isRational() const {
		return false;
	}
	///	@brief Is the expression a real number?
	virtual bool isReal() const {
		return false;
	}
	///	@brief Is the expression a number?
	bool isNum() const {
		return typeInfo_ == NUM;
	}
	///	@brief Is the expression a multiplication?
	bool isMul() const {
		return typeInfo_ == MUL;
	}
	///	@brief Is the expression an addition?
	bool isAdd() const {
		return typeInfo_ == ADD;
	}
	///	@brief Is the expression a variable?
	bool isSym() const {
		return typeInfo_ == SYM;
	}
	///	@brief Is the expression a power?
	bool isPow() const {
		return typeInfo_ == POW;
	}
	///	@brief Is the expression a mathematic function?
	bool isFx() const {
		return typeInfo_ == FX;
	}
protected:
	///	@brief Auxiliary functions for treeView() [indentation].
	void spaces(const int i, std::ostringstream & stream) const;

};
/**	@brief Constainer that is intended for storing operands of multiplications and additions. 
 * 	This type is an alias of a constainer. All containers from STL can be used as basic_container. 
 * 	The library uses warpper functions containerSort for sorting basic_container. These wrappers are implemented 
 * 	for std::vector and std::list and so these containers can be used in this time. If another container
 * 	is required then the function containerSort has to be implemented. 
 * 	@see Add::args_ --> operands of additions
 * 	@see Mul::args_ --> operands of multplication*/
typedef std::list<Ex *> basic_container;
typedef basic_container::iterator iterator;
typedef basic_container::const_iterator const_iterator;
/**	@brief Soring for std::list that contains expressions.
 * 	@param l is sorted list
 * 	@param pf is operator < for expressions
 * 	@see ComparerIx::mullt --> operator< for multiplications
 * 	@see ComparerIx::addlt --> operator< for additions*/ 
void containerSort(std::list<Ex *> & l, bool (* pf)(const Ex * L, const Ex * R));
/**	@brief Soring for std::vector that contains expressions.
 * 	@param l is sorted vector
 * 	@param pf is operator < for expressions 
 * 	@see ComparerIx::mullt --> operator< for multiplications
 * 	@see ComparerIx::addlt --> operator< for additions*/ 
void containerSort(std::vector<Ex *> & v, bool (* pf)(const Ex * L, const Ex * R ));
}
#endif
